#ifndef STRUCTS_H
#define STRUCTS_H

#include <cstdlib>
#include <iostream>

typedef struct nodo_char{
  char valor;
  nodo_char* proximo;
  nodo_char* anterior;
}Sinal;

typedef struct lista_char{
  Sinal* primeiro;
  Sinal* ultimo;
  int tamanho;
}PilhaOp;

typedef struct nodo_float{
  float valor;
  nodo_float* proximo;
  nodo_float* anterior;
}Numero;

typedef struct lista_float{
  Numero* primeiro;
  Numero* ultimo;
  int tamanho;
}PilhaNum;

/* funcoes das estruturas */

PilhaOp cria_pilha_vazia_op(){
  PilhaOp ret;
  ret.tamanho = 0;
  ret.primeiro = NULL;
  ret.ultimo = NULL;
  return ret;
}

PilhaNum cria_pilha_vazia_num(){
  PilhaNum ret;
  ret.tamanho = 0;
  ret.primeiro = NULL;
  ret.ultimo = NULL;
  return ret;
}

//adiciona elemento ao final da pilha
void empilha_op(PilhaOp* pilha,char valor){
  Sinal* novo_elemento =(Sinal*) malloc(sizeof(Sinal));
  novo_elemento->valor = valor;
  novo_elemento->proximo = NULL;

  if(pilha->tamanho == 0){
      novo_elemento->anterior = pilha->primeiro; //null
      novo_elemento->proximo = pilha->ultimo; //null
      pilha->primeiro = novo_elemento;
      pilha->ultimo = novo_elemento;
  }
  else{
    novo_elemento->anterior = pilha->ultimo;
    novo_elemento->proximo = NULL;
    pilha->ultimo->proximo = novo_elemento;
    pilha->ultimo = novo_elemento;
  }
  pilha->tamanho++;
}

void empilha_num(PilhaNum* pilha,float valor){
  Numero* novo_elemento =(Numero*) malloc(sizeof(Numero));
  novo_elemento->valor = valor;
  novo_elemento->proximo = NULL;

  if(pilha->tamanho == 0){
    novo_elemento->anterior = pilha->primeiro; //null
    novo_elemento->proximo = pilha->ultimo; //null
    pilha->primeiro = novo_elemento;
    pilha->ultimo = novo_elemento;
  }
  else{
    novo_elemento->anterior = pilha->ultimo;
    novo_elemento->proximo = NULL;
    pilha->ultimo->proximo = novo_elemento;
    pilha->ultimo = novo_elemento;
  }
  pilha->tamanho++;
}

//remove e retorna ultimo elemento das pilhas
char* remove_op(PilhaOp* pilha){
  char* ret = (char*) malloc(sizeof(char[1]));
  ret[0]= pilha->ultimo->valor;

  if(pilha->tamanho > 1){
    pilha->ultimo = pilha->ultimo->anterior;
    //pilha->ultimo->proximo->anterior = NULL;
    pilha->ultimo->proximo = NULL;
  }
  else{
    pilha->primeiro->proximo = NULL;
    pilha->primeiro == NULL;
    pilha->ultimo->anterior = NULL;
    pilha->ultimo == NULL;
  }

  pilha->tamanho--;
  return ret;
}

float remove_num(PilhaNum* pilha){
  float ret = pilha->ultimo->valor;

  if(pilha->tamanho > 1){
    pilha->ultimo = pilha->ultimo->anterior;
    //pilha->ultimo->proximo->anterior = NULL;
    pilha->ultimo->proximo = NULL;
  }
  else{
    pilha->primeiro->proximo = NULL;
    pilha->primeiro == NULL;
    pilha->ultimo->anterior = NULL;
    pilha->ultimo == NULL;
  }

  pilha->tamanho--;
  return ret;
}

//imprime pilhas
void imprime_pilha_op(PilhaOp pilha){
  Sinal* elemento_atual = pilha.primeiro;
  std::cout << "[ ";
  while(elemento_atual != NULL){
    std::cout << elemento_atual->valor << " ";
    elemento_atual = elemento_atual->proximo;
  }
  std::cout << "]" << std::endl;
}

void imprime_pilha_num(PilhaNum pilha){
  Numero* elemento_atual = pilha.primeiro;
  std::cout << "[ ";
  while(elemento_atual != NULL){
    std::cout << elemento_atual->valor << " ";
    elemento_atual = elemento_atual->proximo;
  }
  std::cout << "]" << std::endl;
}

#endif // STRUCTS_H
